package org.melanesia.sql.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.melanesia.ref.ReleasableResource;

/**
 * Utility class for JDBC object release.
 *
 * @author marcin.kielar
 */
public abstract class JDBCUtils {

    /** Class logger. */
    private static Logger logger = Logger.getLogger(JDBCUtils.class.getName());

    /**
     * Finalizer for sql statements.
     *
     * @author marcin.kielar
     * @see org.melanesia.ref.ReferenceMonitor
     */
    private static class StatementFinalizer extends ReleasableResource<Statement> {

        /**
         * Constructs new {@code StatementFinalizer} for given releasable
         * resource.
         *
         * @param resource
         *            releasable resource
         */
        public StatementFinalizer(final Statement resource) {
            super(resource);
        }

        @Override
        public void release() {
            JDBCUtils.close(get());
        }

        @Override
        public boolean isReleased() {
            return JDBCUtils.isClosed(get());
        }
    }

    /**
     * Finalizer for sql result sets.
     *
     * @author marcin.kielar
     * @see org.melanesia.ref.ReferenceMonitor
     */
    private static class ResultSetFinalizer extends ReleasableResource<ResultSet> {

        /**
         * Constructs new {@code ResultSetFinalizer} for given releasable
         * resource.
         *
         * @param resource
         *            releasable resource
         */
        public ResultSetFinalizer(final ResultSet resource) {
            super(resource);
        }

        @Override
        public void release() {
            JDBCUtils.close(get());
        }

        @Override
        public boolean isReleased() {
            return JDBCUtils.isClosed(get());
        }
    }

    /**
     * Closes jdbc connection.
     *
     * @param connection
     *            jdbc connection to close
     */
    public static final void close(final Connection connection) {
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (Throwable t) {
            logger.log(Level.WARNING, "Error closing connection.", t);
        }
    }

    /**
     * Closes jdbc statement.
     *
     * @param statement
     *            jdbc statement to close
     */
    public static final void close(final Statement statement) {
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (Throwable t) {
            logger.log(Level.WARNING, "Error closing statement.", t);
        }
    }

    /**
     * Closes jdbc result set.
     *
     * @param resultSet
     *            jdbc result set to close
     */
    public static final void close(final ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (Throwable t) {
            logger.log(Level.WARNING, "Error closing result set.", t);
        }
    }

    /**
     * Checks whether the sql statement is closed.
     *
     * @param statement
     *            statement to check
     * @return true/false depending on the state of the statement
     */
    public static final boolean isClosed(final Statement statement) {
        try {
            return statement == null || statement.isClosed();
        } catch (Throwable t) {
        	return true;
        }
    }

    /**
     * Checks whether the sql result set is closed.
     *
     * @param resultSet
     *            result set to check
     * @return true/false depending on the state of the result set
     */
    public static final boolean isClosed(final ResultSet resultSet) {
        try {
            return resultSet == null || resultSet.isClosed();
        } catch (Throwable t) {
            return true;
        }
    }

    /**
     * Creates a finalized for sql statement.
     *
     * @param statement
     *            statement to create a finalizer for
     * @return finalizer
     * @see org.melanesia.ref.ReferenceMonitor
     */
    public static final ReleasableResource<Statement> createFinalizer(final Statement statement) {
        return new StatementFinalizer(statement);
    }

    /**
     * Creates a finalized for sql result set.
     *
     * @param resultSet
     *            result set to create a finalizer for
     * @return finalizer
     * @see org.melanesia.ref.ReferenceMonitor
     */
    public static final ReleasableResource<ResultSet> createFinalizer(final ResultSet resultSet) {
        return new ResultSetFinalizer(resultSet);
    }
}
